package com.spukmk3me.video;

import com.spukmk3me.scene.Entity;
import com.spukmk3me.util.DiscreteTimedAnimation;

public abstract class Sprite extends Entity
{
    protected Sprite( Image image, int x, int y, int w, int h, int spriteW, int spriteH, int[] framePositions, int[] frameSteps )
    {
        super( image );
        
        this.image = image; 
        
        x = Math.max( x, 0 );
        x = Math.min( x, image.width() );
        y = Math.max( y, 0 );
        y = Math.min( y, image.height() );
        w = Math.max( w, 0 );
        w = Math.min( w, image.width() - x );
        h = Math.max( h, 0 );
        h = Math.min( h, image.height() - y );
        
        this.x          = x;
        this.y          = y;
        this.spriteW    = spriteW;
        this.spriteH    = spriteH;
        nW              = w / spriteW;
        nH              = h / spriteH;
        
        if ( framePositions == null )
        {
            if ( (nW == 0) || (nH == 0) )
                m_framePositions = null;
            else
            {
                m_framePositions = new int[ nW * nH ];
                
                for ( int i = 0; i != m_framePositions.length; ++i )
                    m_framePositions[ i ] = i;
            }
        }
        else
            m_framePositions = framePositions;
        
        m_timedAnimation = new DiscreteTimedAnimation( frameSteps );
    }
    
    @Override
    public final byte getType()
    {
        return ET_SPRITE;
    }
    
    @Override
    public final int getWidth()
    {
        return spriteW;
    }
    
    @Override
    public final int getHeight()
    {
        return spriteH;
    }
    
    @Override
    public final boolean isTimeless()
    {
        return false;
    }

    public final void update( int deltaTime )
    {
        m_timedAnimation.update( deltaTime );
    }
    
    public final int[] getFrameSteps()
    {
        return m_timedAnimation.getFrameSteps();
    }
    
    /**
     *  @return The current frame index.
     */
    public final int getFrameIndex()
    {
        return m_timedAnimation.getFrameIndex();
    }
    
    public final int getFramePosition( int frameIndex )
    {
        return m_framePositions[ frameIndex ];
    }

    /**
     *  Set the frame index of this sprite.
     *  @param frameIndex The index of the frame.
     */
    public final void setFrameIndex( int frameIndex )
    {
        m_timedAnimation.setFrameIndex( frameIndex );
    }
    
    /**
     *  Setup the animation.
     *  @param mode The animating mode. Can be combined from MODE_BACKWARD,
     * MODE_FRAMESTOP, MODE_ANIMATING, MODE_AUTODROP.
     *  @param firstIndex The first frame index of animated frame sequence.
     *  @param lastFrame The last frame index of animated frame sequence.
     *  @param msPerFrame Amount of time for a frame, measured in milliseconds.
     * Pass -1 value to this parameter if you want to keep the old msPerFrame.
     *  @param nFrameToStop The animation will stop after nFrameToStop frames.
     * Ignored if the mode doesn't contain MODE_FRAMESTOP.
     */
    public final void setAnimating( int mode, int firstIndex, int lastIndex,
        int msPerFrame, int nFrameToStop )
    {
        m_timedAnimation.setAnimating( mode, firstIndex, lastIndex, msPerFrame, nFrameToStop );
    }

    /**
     *  Check if the sprite is animating or not.
     *  @return true if this sprite is animating, otherwise return false.
     */
    public final boolean isAnimating()
    {
        return m_timedAnimation.isAnimating();
    }
    
    //! If the MODE_ANIMATING bit is zero, the animation won't animate.
    public static final byte    MODE_ANIMATING      = DiscreteTimedAnimation.MODE_ANIMATING;
    //! If the MODE_BACKWARD bit is zero, forward animation is used.
    public static final byte    MODE_BACKWARD       = DiscreteTimedAnimation.MODE_BACKWARD;
    //! Stop after pre-defined number of frames.
    public static final byte    MODE_FRAMESTOP      = DiscreteTimedAnimation.MODE_FRAMESTOP;

    public final Image  image;
    public final int    x, y, nW, nH, spriteW, spriteH;
    
    protected int[]         m_framePositions;
    private DiscreteTimedAnimation  m_timedAnimation;
}
